/*
 *
 * @ProjectName:    my_umi_app
 * @Package:
 * @ClassName:      add_article
 * @Description:    添加文章
 * @Author:         SuPeiSen
 * @CreateDate:     2021/1/26 10:23 上午
 * @UpdateDate:     2021/1/26 10:23 上午
 * @UpdateRemark:   更新说明：
 * @Version:        1.0
 */

import {
  Form,
  Input,
  Row,
  Select,
  Switch,
  Tag,
  Button,
  message,
  Space,
} from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import './style/add_article_style.less';
import { CustomTagProps } from 'rc-select/lib/interface/generator';
import { getAllTagApi, getTagListApi } from '@/service/tap_api';
import { numberToBool, rgbaColorByString } from '@/utils/app_fun';
import { uploadFileToQiNiuApi } from '@/service/upload_api';
import { Editor } from '@tinymce/tinymce-react';
import { AppConfig, AppImageUrl } from '@/config/app_config';
import { QiNiuUploadWidget } from '@/widget/qiniu_upload_widget/qiniu_upload_widget';
import { MinusCircleOutlined, EnvironmentOutlined } from '@ant-design/icons';
import { getCategoryApi } from '@/service/category_api';
import {
  AddArticleApi,
  GetArticleDetailsByAdminApi,
  UpdateArticleDetailsByAdminApi,
} from '@/service/article_api';
import { ArticleListItemType } from '@/type/article_type';
import { IRouteComponentProps } from 'umi';

interface CategoryParam {
  id?: string;
  article_image?: string;
}

export default (props: IRouteComponentProps<{}, CategoryParam>) => {
  // get参数
  const queryParam = props.location.query;

  const articleModelRef = useRef<ArticleListItemType | undefined>(undefined);
  // const articleModel = articleModelRef.current;

  // 使用useForm创建form对象
  const [form] = Form.useForm();

  const { Option } = Select;

  // 保存选中的标签
  let articleSelectTagId = useRef<{ value: Array<number> }>({ value: [] });
  // 保存文章展示图片url
  const articleUrl = useRef<{ url: string }>({ url: '' });
  // 保存文章名称
  const articleNameRef = useRef<Input>(null);
  // 保存文章简介
  const articleSynopsis = useRef<{ value: string }>({ value: '' });
  // 保存选中的分类
  const articleCategorySelectRef = useRef<{ selectId: number }>({
    selectId: -1,
  });
  // 文章内容
  let articleContent = useRef<{ content: string }>({ content: '' });
  // 是否上架
  let articleStatus = useRef<{ value: boolean }>({
    value: numberToBool(articleModelRef.current?.article_status),
  });
  // 是否置顶
  let articleSticky = useRef<{ value: boolean }>({
    value: numberToBool(articleModelRef.current?.article_sticky),
  });
  // 是否原创
  let articleOriginate = useRef<{ value: boolean }>({
    value: numberToBool(articleModelRef.current?.article_originate),
  });
  // 参考链接
  let articleConsult = useRef<{
    value: Array<{ consultName: string; consultUrl: string }>;
  }>({
    value:
      articleModelRef.current?.article_consult.map((item) => {
        return { consultName: item.consultName, consultUrl: item.consultUrl };
      }) ?? [],
  });

  // button-loading
  const [btnLoading, setBtnLoading] = useState<boolean>(false);
  // tag-select-loading
  const [tagSelectLoading, setTagSelectLoading] = useState<boolean>(true);
  // select-loading
  const [categorySelectLoading, setCategorySelectLoading] = useState<boolean>(
    true,
  );
  // 保存获取到Tags数据
  const [tagSelectValue, setTagSelectValue] = useState<
    Array<{
      value: string;
      label: string;
      id: number;
    }>
  >([]);
  // 保存获取到Tags数据
  const [categorySelectValue, setCategorySelectValue] = useState<
    Array<{
      value: string;
      id: number;
    }>
  >([]);

  // 获取文章详情,用于修改文章
  if (queryParam.id !== undefined) {
    useEffect(() => {
      GetArticleDetailsByAdminApi(Number(queryParam.id)).then((model) => {
        if (model.success) {
          const value = model.data!.data;
          articleModelRef.current = value;
          // 保存数据
          articleUrl.current.url = value.article_image;
          articleCategorySelectRef.current.selectId = value.articleCategory.id;
          articleSelectTagId.current.value = value.articleTag.map(
            (item) => item.id,
          );
          articleContent.current.content = value.article_content;
          articleStatus.current.value = numberToBool(value.article_status);
          articleSticky.current.value = numberToBool(value.article_sticky);
          articleOriginate.current.value = numberToBool(
            value.article_originate,
          );
          articleConsult.current.value = value.article_consult;
          articleSynopsis.current.value = value.article_synopsis;

          // 更新表单内容
          form.setFieldsValue({
            article_name: value.article_title,
            article_category: value.articleCategory.category_name,
            article_tag: value.articleTag.map((item) => {
              return rgbaColorByString(item.tag_color);
            }),
            article_content: `${value.article_content}`,
            article_status: numberToBool(value.article_status),
            article_sticky: numberToBool(value.article_sticky),
            article_originate: numberToBool(value.article_originate),
            article_consult: value.article_consult,
            article_synopsis: value.article_synopsis,
          });
        }
      });
    }, []);
  }

  // 获取Tags
  useEffect(() => {
    getAllTagApi(() => {
      setTagSelectLoading(false);
    }).then((model) => {
      if (model.success) {
        const tags = model.data!.data;
        let optionsList: Array<{
          value: string;
          label: string;
          id: number;
        }> = [];
        tags.forEach((tag) => {
          const rgbaColor = rgbaColorByString(tag.tag_color);
          optionsList.push({
            value: rgbaColor,
            label: tag.tag_name,
            id: tag.id,
          });
        });
        setTagSelectValue(optionsList);
      }
    });
  }, []);

  // 获取分类
  useEffect(() => {
    getCategoryApi(() => {
      setCategorySelectLoading(false);
    }).then((model) => {
      if (model.success) {
        const categoryList = model.data!.data;
        let optionsList: Array<{
          value: string;
          id: number;
        }> = [];
        categoryList.forEach((category) => {
          optionsList.push({
            value: category.category_name,
            id: category.id,
          });
        });
        setCategorySelectValue(optionsList);
      }
    });
  }, []);

  // Form表单一些样式配置
  const formItemLayout = {
    labelCol: { span: 2 },
    wrapperCol: { span: 22 },
  };
  const buttonLayout = {
    wrapperCol: { offset: 2, span: 22 },
  };

  // 生成标签
  const tagRender = function (props: CustomTagProps): React.ReactElement {
    const { label, value, closable, onClose } = props;
    return (
      <Tag
        color={value as string}
        closable={closable}
        onClose={onClose}
        style={{ marginRight: 3 }}
      >
        {label}
      </Tag>
    );
  };

  // 提交表单
  const addArticle = async () => {
    setBtnLoading(true);
    const tagsArray: Array<number> = [];
    articleSelectTagId.current.value.forEach((item) => {
      tagsArray.push(item);
    });
    const consultArray = articleConsult.current.value.map((value) =>
      JSON.stringify(value),
    );
    const postParam = {
      article_title: articleNameRef.current!.state.value,
      article_category: articleCategorySelectRef.current.selectId,
      article_image: articleUrl.current.url,
      article_tag: tagsArray,
      article_content: articleContent.current.content,
      article_status: articleStatus.current.value,
      article_sticky: articleSticky.current.value,
      article_originate: articleOriginate.current.value,
      article_consult: consultArray,
      article_synopsis: articleSynopsis.current.value,
    };
    if (queryParam.id !== undefined) {
      // 修改文章
      const articleIdObj = { id: queryParam.id };
      const param = Object.assign(postParam, articleIdObj);
      const success = await UpdateArticleDetailsByAdminApi(param, () =>
        setBtnLoading(false),
      );
      if (success) {
        message.success('成功');
      } else {
        message.error('失败');
      }
    } else {
      // 添加文章
      const success = await AddArticleApi(postParam, () =>
        setBtnLoading(false),
      );
      props.history.push('/admin/article/article_list');
      if (success) {
        message.success('成功');
      } else {
        message.error('失败');
      }
    }
  };

  return (
    <div className="add_article_main_div">
      <Form {...formItemLayout} onFinish={addArticle} form={form}>
        {/*文章名称*/}
        <Form.Item
          label="文章名称"
          name="article_name"
          className="article_input_len"
          rules={[{ required: true, message: '请填写文章名称!' }]}
        >
          <Input ref={articleNameRef} placeholder="请填写文章名称" />
        </Form.Item>

        {/*所属分类*/}
        <Form.Item
          label="所属分类"
          name="article_category"
          className="article_input_len"
        >
          <Select
            placeholder="请选择对应分类"
            loading={categorySelectLoading}
            onChange={(value, option) => {
              if ('key' in option) {
                articleCategorySelectRef.current.selectId = Number(option.key);
              }
            }}
          >
            {categorySelectValue.map((categoryItem) => {
              return (
                <Option value={categoryItem.value} key={categoryItem.id}>
                  {categoryItem.value}
                </Option>
              );
            })}
          </Select>
        </Form.Item>

        {/*文章图片*/}
        <Form.Item
          label="文章图片"
          name="article_image"
          className="article_input_len"
          valuePropName="fileList"
        >
          <QiNiuUploadWidget
            onSelect={(url) => {
              articleUrl.current.url = url;
            }}
            initValue={
              queryParam.article_image === undefined
                ? []
                : [
                    {
                      uid: `${queryParam.id}`,
                      name: queryParam.article_image,
                      status: 'done',
                      type: '',
                      url: AppImageUrl(queryParam.article_image),
                      size: 0,
                    },
                  ]
            }
          />
        </Form.Item>

        {/*相关标签*/}
        <Form.Item
          label="相关标签"
          name="article_tag"
          className="article_input_len"
        >
          <Select
            loading={tagSelectLoading}
            onChange={(value, option) => {
              try {
                articleSelectTagId.current.value = [];
                const items = value as Array<{
                  value: string;
                  label: string;
                  id: number;
                }>;
                items.forEach((tag, index) => {
                  const optionArr = option as Array<any>;
                  articleSelectTagId.current.value.push(optionArr[index].id);
                });
              } catch (e) {
                console.log(e);
              }
            }}
            style={{ width: '100%' }}
            mode="multiple"
            options={tagSelectValue}
            tagRender={tagRender}
            placeholder="请选择与文章相关标签"
          />
        </Form.Item>

        {/*文章简介*/}
        <Form.Item
          label="文章简介"
          className="article_input_len"
          name="article_synopsis"
          rules={[{ required: true, message: '请填写文章简介!' }]}
        >
          <Input.TextArea
            autoSize={{ minRows: 2, maxRows: 6 }}
            onChange={(event) => {
              articleSynopsis.current.value = event.target.value;
            }}
          />
        </Form.Item>

        {/*富文本*/}
        <Form.Item
          label="内容"
          name="article_content"
          // (玄学哈哈哈哈)加上这一段就不会报错了
          // Failed prop type: Invalid prop `value` of type `object` supplied to `Editor`, expected `string`.
          normalize={(value, prevValue, allValues) => {}}
          initialValue={articleModelRef.current?.article_content ?? ''}
          className="article_input_len"
        >
          <Editor
            apiKey={AppConfig.TinyEditKey}
            cloudChannel="5-stable"
            disabled={false}
            onEditorChange={(value) => {
              articleContent.current.content = value;
            }}
            id="blog.hellosu.top/admin"
            init={{
              language: 'zh_CN',
              images_upload_base_path: '',
              images_upload_url: '',
              height: '500px',
              automatic_uploads: true,
              images_upload_handler: async function (
                blobInfo,
                successFun,
                failFun,
              ) {
                const file = blobInfo.blob();
                const re = await uploadFileToQiNiuApi(
                  file,
                  successFun,
                  failFun,
                );
              },
              toolbar1: initToolbar1,
              codesample_languages: initCodeLanguage,
            }}
            inline={false}
            plugins={initPlugins}
          />
        </Form.Item>

        {/*上架*/}
        <Form.Item
          label="上架"
          className="article_input_len"
          valuePropName="checked"
          name="article_status"
          initialValue={numberToBool(articleModelRef.current?.article_status)}
        >
          <Switch onChange={(value) => (articleStatus.current.value = value)} />
        </Form.Item>

        {/*置顶*/}
        <Form.Item
          label="置顶"
          valuePropName="checked"
          name="article_sticky"
          className="article_input_len"
          initialValue={numberToBool(articleModelRef.current?.article_sticky)}
        >
          <Switch onChange={(value) => (articleSticky.current.value = value)} />
        </Form.Item>

        {/*原创*/}
        <Form.Item
          label="原创"
          className="article_input_len"
          valuePropName="checked"
          name="article_originate"
          initialValue={numberToBool(
            articleModelRef.current?.article_originate,
          )}
        >
          <Switch
            onChange={(value) => (articleOriginate.current.value = value)}
          />
        </Form.Item>

        {/*参考链接*/}
        <Form.List
          initialValue={articleModelRef.current?.article_consult ?? []}
          name="article_consult"
        >
          {(fields, { add, remove }, meta) => {
            return (
              <>
                {fields.map((field, index) => {
                  return (
                    <Form.Item
                      label={`参考${index + 1}`}
                      {...field}
                      className="article_input_len"
                      name={`article_consult_${index}`}
                    >
                      <div className="add_article_consult" key={field.key}>
                        <Input
                          placeholder={`参考内容标题:${index + 1}`}
                          style={{ marginRight: '2%' }}
                          name={`consult_name_${index}`}
                          defaultValue={
                            articleModelRef.current?.article_consult[index]
                              .consultName ?? ''
                          }
                          onChange={(element) => {
                            articleConsult.current.value[index].consultName =
                              element.target?.value;
                          }}
                        />
                        <Input
                          placeholder={`参考内容URL:${index + 1}`}
                          defaultValue={
                            articleModelRef.current?.article_consult[index]
                              .consultUrl ?? ''
                          }
                          style={{ marginRight: '2%' }}
                          name={`consult_url_${index}`}
                          onChange={(element) => {
                            articleConsult.current.value[index].consultUrl =
                              element.target?.value;
                          }}
                        />
                        <MinusCircleOutlined
                          style={{ color: 'red' }}
                          onClick={() => {
                            remove(field.name);
                            articleConsult.current.value.splice(index, 1);
                          }}
                        />
                        <div style={{ width: '2%' }} />
                        <EnvironmentOutlined
                          style={{ color: '#be30ad' }}
                          onClick={(element) => {
                            window.open(
                              articleConsult.current.value[index].consultUrl,
                            );
                          }}
                        />
                      </div>
                    </Form.Item>
                  );
                })}
                <Form.Item className="article_input_len" {...buttonLayout}>
                  <Button
                    type="primary"
                    style={{ backgroundColor: '#36c971', border: '0' }}
                    onClick={() => {
                      add();
                      articleConsult.current.value.push({
                        consultName: '',
                        consultUrl: '',
                      });
                    }}
                  >
                    添加参考链接
                  </Button>
                </Form.Item>
              </>
            );
          }}
        </Form.List>

        <Form.Item {...buttonLayout} className="article_input_len">
          <Button
            type="primary"
            htmlType="submit"
            size="large"
            loading={btnLoading}
          >
            保存
          </Button>
          <a
            style={{ marginLeft: '2%' }}
            hidden={queryParam.id === undefined}
            target="_blank"
            rel="noopener noreferer"
            href={'/admin/article/preview_article?id=' + queryParam.id}
          >
            预览
          </a>
        </Form.Item>
      </Form>
    </div>
  );
};

/**
 * 标签选择
 * @constructor
 */
export const TagSelect = (props: {
  onSelect: (value: any) => void;
  options: Array<{ value: string; label: string; id: number }>;
  loading: boolean;
}) => {
  const tagRender = function (props: CustomTagProps): React.ReactElement {
    const { label, value, closable, onClose } = props;
    return (
      <Tag
        color={value as string}
        closable={closable}
        onClose={onClose}
        style={{ marginRight: 3 }}
      >
        {label}
      </Tag>
    );
  };

  return (
    <Select
      loading={props.loading}
      onChange={(value, option) => {
        props.onSelect(option);
      }}
      style={{ width: '100%' }}
      mode="multiple"
      options={props.options}
      tagRender={tagRender}
      placeholder="请选择与文章相关标签"
    />
  );
};

/**
 * 选择分类
 * @param props
 * @constructor
 */
const CategorySelect = (props: {
  onSelect: (selectId: number) => void;
  defaultValue?: any;
  loading: boolean;
  categoryArrayValue: Array<{ value: string; id: number }>;
}) => {
  const { Option } = Select;
  return (
    <Select
      placeholder="请选择对应分类"
      defaultValue={props.defaultValue}
      loading={props.loading}
      onChange={(value, option) => {
        if ('key' in option) {
          props.onSelect(Number(option.key));
        }
      }}
    >
      {props.categoryArrayValue.map((categoryItem) => {
        return (
          <Option value={categoryItem.value} key={categoryItem.id}>
            {categoryItem.value}
          </Option>
        );
      })}
    </Select>
  );
};

// Tiny配置
const initToolbar1 =
  'undo redo toc |  styleselect | bold italic | alignleft aligncenter alignright alignjustify | ' +
  'bullist numlist outdent indent | link image | print preview  | ' +
  'forecolor backcolor emoticons |  codesample blockquote | fullscreen help';
export const initCodeLanguage = [
  { text: 'HTML/XML', value: 'markup' },
  { text: 'XML', value: 'xml' },
  { text: 'HTML', value: 'html' },
  { text: 'SVG', value: 'svg' },
  { text: 'CSS', value: 'css' },
  { text: 'Clike', value: 'clike' },
  { text: 'Javascript', value: 'javascript' },
  { text: 'bash', value: 'bash' },
  { text: 'basic', value: 'basic' },
  { text: 'c', value: 'c' },
  { text: 'C#', value: 'csharp' },
  { text: 'C++', value: 'cpp' },
  { text: 'ruby', value: 'ruby' },
  { text: 'dart', value: 'dart' },
  { text: 'docker', value: 'docker' },
  { text: 'git', value: 'git' },
  { text: 'go', value: 'go' },
  { text: 'http', value: 'http' },
  { text: 'icon', value: 'icon' },
  { text: 'java', value: 'java' },
  { text: 'JSON', value: 'json' },
  { text: 'jsonp', value: 'jsonp' },
  { text: 'kotlin', value: 'kotlin' },
  { text: 'less', value: 'less' },
  { text: 'markdown', value: 'markdown' },
  { text: 'matlab', value: 'matlab' },
  { text: 'nginx', value: 'nginx' },
  { text: 'objectivec', value: 'objectivec' },
  { text: 'perl', value: 'perl' },
  { text: 'PHP', value: 'php' },
  { text: 'python', value: 'python' },
  { text: 'r', value: 'r' },
  { text: 'jsx', value: 'jsx' },
  { text: 'rest', value: 'rest' },
  { text: 'rip', value: 'rip' },
  { text: 'rust', value: 'rust' },
  { text: 'sass', value: 'sass' },
  { text: 'scss', value: 'scss' },
  { text: 'scala', value: 'scala' },
  { text: 'smarty', value: 'smarty' },
  { text: 'SQL', value: 'sql' },
  { text: 'stylus', value: 'stylus' },
  { text: 'swift', value: 'swift' },
  { text: 'tcl', value: 'tcl' },
  { text: 'TypeScript', value: 'typescript' },
  { text: 'YAML', value: 'yaml' },
];
const initPlugins = [
  'codesample image toc',
  'advlist autolink link image lists charmap print preview hr anchor pagebreak',
  'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking',
  'table emoticons template paste help',
];
